/**
 * Copyright (c) 2022-2024 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef PANDA_ECMA_INLINING_H
#define PANDA_ECMA_INLINING_H

#include "compiler/optimizer/optimizations/inlining.h"
#include "compiler/optimizer/ir/runtime_interface.h"

namespace ark::compiler::ecmascript {

class EcmaInlining : public Inlining {
public:
    using Inlining::Inlining;

    explicit EcmaInlining(Graph *graph, uint32_t instructionsCount, uint32_t methodsInlined,
                          const ArenaVector<RuntimeInterface::MethodPtr> *inlinedStack);
    explicit EcmaInlining(Graph *graph) : EcmaInlining(graph, 0, 0, nullptr) {};

    NO_MOVE_SEMANTIC(EcmaInlining);
    NO_COPY_SEMANTIC(EcmaInlining);
    ~EcmaInlining() override = default;
    static void BuildGuard(CallInst *callInst, RuntimeInterface::MethodPtr methodPtr);

private:
    void RunOptimizations() const override;
    bool IsInstSuitableForInline(Inst *inst) const override;
    bool SkipBlock(const BasicBlock *block) const override;

    bool TryInline(CallInst *callInst) override;
    bool DoEcmaMonomorphicInilning(CallInst *callInst, InlineContext &ctx);
    bool DoEcmaPolymorphicInilning(CallInst *callInst);
    bool ResolveTargets(CallInst *callInst);
    RuntimeInterface::MethodPtr TryResolveTargetStatic(CallInst *callInst) const;
    bool IsInstSuitableForEcmaStaticInlining(Inst *defineFunc) const;
    bool CheckCallKind(CallInst *callInst);
    bool CheckMethod(CallInst *callInst, InlineContext *ctx);
    Graph *BuildGraph(InlineContext *ctx, CallInst *callInst, CallInst *newCallInst = nullptr);
    void CreateCompareFunctions(CallInst *callInst, RuntimeInterface::MethodPtr methodPtr, BasicBlock *callBb);
    void InsertGraph(CallInst *callInst, const InlineContext &ctx, Graph *graphInl);
    bool IsStaticInlining() const
    {
        return jsFunctions_.empty();
    }
    bool CheckInlinableBuiltin(CallInst *callInst, RuntimeInterface::MethodPtr nativeMethod);

    bool IsMonomorphicInlining() const
    {
        return jsFunctions_.size() == 1U;
    }

private:
    // This vector contains pointers to element in EcmaCallProfilingTable
    // This element contains pointer to js function
    ArenaVector<uintptr_t> jsFunctions_;
};

}  // namespace ark::compiler::ecmascript

#endif  // PANDA_ECMA_INLINING_H